import cn.hutool.crypto.digest.MD5;
import model.User;
import util.DBUtil;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpSocketLoginServer {
    public static void main(String[] args) throws IOException,SQLException {
        TcpSocketLoginServer server = new TcpSocketLoginServer(9091);
        server.start();
    }
    // 1. 创建 serverSocket
    private ServerSocket serverSocket = null;

    public TcpSocketLoginServer(int port) throws IOException {
        // 2. 根据端口号进入具体服务
        serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动！");
        // 3. 定义线程池
        ExecutorService pool = Executors.newCachedThreadPool();
        while (true) {
            // 4. 调用 assept 建立短连接
            Socket clientSocket = serverSocket.accept();
            // 5. 从线程池获取一个线程来执行任务
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processLoginConnection(clientSocket);
                    }  catch (IOException | SQLException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    /**
     * 处理验证身份信息功能任务
     * @param socket 连接信息
     */
    @edu.umd.cs.findbugs.annotations.SuppressFBWarnings({"VA_FORMAT_STRING_USES_NEWLINE", "DM_DEFAULT_ENCODING", "DM_DEFAULT_ENCODING"})
    private void processLoginConnection(Socket socket) throws IOException, SQLException {
        System.out.println("验证身份信息功能启动......");
        System.out.printf("[%s:%d] 客户端建立连接!\n", socket.getInetAddress().toString(), socket.getPort());
        // 获取输入/输出流信息
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner = new Scanner(br);
        // 5.1 循环处理每个请求，分别返回响应
        while (true) {
            // 5.2 接收客户端数据
            String json = scanner.next(); // 读一行数据
            String[] infos = json.split(",");
            String username = infos[0];
            String password = infos[1];
            if(!"".equals(username) || !"".equals(password)) {
                // 5.3 操作数据库
                // 5.3.1 得到数据库连接 connection
                Connection connection = DBUtil.getConnection();
                String sql = "select username,password from user where username=? and password=?";
                PreparedStatement statement = connection.prepareStatement(sql
                        ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); /*这里这个参数解决了后续查询游标不能移动的问题*/
                // 5.3.2 填充占位符
                statement.setString(1, username);
                statement.setString(2, MD5.create().digestHex(password));
                // 5.3.3 执行 SQL
                ResultSet result = statement.executeQuery();
                while (result.next()) {
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    bw.write(".查询身份信息成功，身份信息存在......\n");
                    System.out.println("查询身份信息成功，身份信息存在......");
                    System.out.println(user);
                    System.out.println();
                }
                result.last(); // 将光标移动到最后一行
                int rowCount = result.getRow(); // 得到当前行号，即结果集记录数
                if(rowCount < 1) {
                    bw.write(rowCount);
                    bw.write("查询身份信息失败，身份信息不存在......\n");
                    System.err.println("查询身份信息失败，身份信息不存在......\n");
                }
                // 5.4 关闭资源
                DBUtil.close(statement, connection);
            } else {
                System.err.println("参数错误");
            }
            // 6 关闭并刷新
            bw.newLine();
            bw.flush();
            bw.close();
            socket.close();
        }
    }
}